package com.itheima.advice;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.pojo.Log;
import com.itheima.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;

@Aspect
@Component
public class LogAdvicer {
    @Reference
    private LogService logService;

    @Around(value = "execution( * com.itheima.controller.*.*(..))")
    public Object around(ProceedingJoinPoint pjp){
        try {
            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = sra.getRequest();
            //ip
            String ip = getIpAddress(request);
            long timeBefore = System.currentTimeMillis();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String currentTime = sdf.format(timeBefore);

            Object[] args = pjp.getArgs();
            Object result = pjp.proceed(args);

            long timeAfter=System.currentTimeMillis();
            long time=timeAfter-timeBefore;
            //方法执行时长
            String executeTime=time+"ms";
            //目标类
            String className = pjp.getTarget().getClass().getSimpleName();
            //方法
            String methodName = pjp.getSignature().getName();
            //目标资源
            String url="/"+className+"/"+methodName;
            //用户名
            String username=getCurrentUserName();
            System.out.println("username:"+username+"---url:"+url+"---executeTime:"+executeTime
                    +"---ip:"+ip+"---optionTime:"+currentTime);

            Log log = new Log(username, currentTime, ip, url, executeTime);
            logService.add(log);

            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }

    }

    //获取IP
    public static String getIpAddress(HttpServletRequest request) {
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        if (ip.equals("127.0.0.1")) {
            InetAddress inetAddress = null;
            try {
                try {
                    inetAddress = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            } catch (Exception e) {

                e.printStackTrace();
            }
            ip = inetAddress.getHostAddress();
        }
        return ip;
    }

    //获取用户名
    public String getCurrentUserName(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            String currentUserName = authentication.getName();
            return currentUserName;
        }
        return null;
    }
}
